package cn.ztf.zshop.sys.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.ztf.zshop.common.exception.ZShopException;
import cn.ztf.zshop.security.admin.constant.SaSessionCacheKey;
import cn.ztf.zshop.security.admin.constant.SaSessionName;
import cn.ztf.zshop.sys.dao.SysMenuDao;
import cn.ztf.zshop.sys.dao.SysRoleDao;
import cn.ztf.zshop.sys.vo.MenuVo;
import cn.ztf.zshop.sys.po.Menu;
import cn.ztf.zshop.sys.service.SysMenuService;
import cn.ztf.zshop.sys.dto.MenuDto;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, Menu> implements SysMenuService {

    @Autowired
    private final MapperFacade mapperFacade;

    private final SysRoleDao sysRoleDao;


    //todo 这段代码比较重复
    @Override
    public List<MenuVo> listTree() {
        List<Menu> menuList = baseMapper.selectList(null);
        HashMap<Long, MenuVo> map = new HashMap<>();
        for (Menu menu : menuList) {
            MenuVo menuVo = mapperFacade.map(menu, MenuVo.class);
            map.put(menu.getMenuId(), menuVo);
        }
        List<MenuVo> linkedList = new LinkedList<>();
        for (MenuVo menuVo : map.values()) {
            MenuVo parent = map.get(menuVo.getParentId());
            if (ObjectUtils.isEmpty(parent)) {
                linkedList.add(menuVo);
            } else {
                List<MenuVo> menuVoList = parent.getChildren();
                if (ObjectUtils.isEmpty(menuVoList)) {
                    menuVoList = new LinkedList<>();
                    parent.setChildren(menuVoList);
                }
                menuVoList.add(menuVo);
            }

        }
        return linkedList;
    }

    @Override
    public MenuVo getMenuById(Long id) {
        Menu menu = baseMapper.selectById(id);
        MenuVo menuVo = mapperFacade.map(menu, MenuVo.class);
        return menuVo;
    }

    @Override
    public void addMenu(MenuDto menuDto) {
        Menu menu = mapperFacade.map(menuDto, Menu.class);
        baseMapper.insert(menu);
        // todo  update or delete
        SaSessionCustomUtil.deleteSessionById("permission:list");
    }

    @Override
    public void updateMenu(MenuDto menuDto) {
        Menu menu = mapperFacade.map(menuDto, Menu.class);
        baseMapper.updateById(menu);

        // 查询哪些角色拥有此菜单,并删除这些角色的权限缓存
        SaSessionCustomUtil.deleteSessionById("permission:list");
        List<Long> roleIds = sysRoleDao.findRoleByMenu(menu.getMenuId());
        for (Long roleId : roleIds) {
            SaSessionCustomUtil.deleteSessionById("role:" + roleId);
        }

    }

    @Override
    public void deletedMenuVById(Long menuId) {
        List<Long> roleIds = sysRoleDao.findRoleByMenu(menuId);
        if (!ObjectUtils.isEmpty(roleIds)){
            // 当前菜单被角色正在占用
            throw new ZShopException("当前菜单正在被角色占用,请检查");
        }
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getParentId, menuId);
        Long count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            // 无法删除非叶子节点
            throw new ZShopException("无法删除非根节点数据");
        }
        baseMapper.deleteById(menuId);
        SaSession permissionSession = SaSessionCustomUtil.getSessionById(SaSessionName.PERMISSIONS);
        permissionSession.delete(SaSessionCacheKey.PERMISSION_all_CACHE_KEY);
        List<Long> roleIdList = sysRoleDao.findRoleByMenu(menuId);
        for (Long roleId : roleIdList) {
            SaSessionCustomUtil.deleteSessionById("role:" + roleId);
        }
    }
}

